#include "chessbox.hpp"
#include "config.hpp"
#include <array>
#include <iostream>
#include <opencv2/core/types.hpp>
#include <opencv2/highgui.hpp>
#include <ostream>
#include <string>

// 静态成员初始化
JingZiqiSimulator *JingZiqiSimulator::instance = nullptr;

JingZiqiSimulator::JingZiqiSimulator()
    : board_state(GRID_SIZE,
                  std::vector<chessPiece>(GRID_SIZE, chessPiece::NONE)),
      current_player(chessPiece::BLACK), game_ended(false),
      winner(chessPiece::NONE),
      canvas(WINDOW_SIZE, WINDOW_SIZE, CV_8UC3, cv::Scalar(240, 240, 240)),
      is_vs_computer(false), is_player_first(true),
      player_piece(chessPiece::BLACK), computer_piece(chessPiece::WHITE) {

  instance = this;
  chess_ = std::make_shared<Game>();
  sr_ = std::make_shared<serial>();

  draw_board();
}

JingZiqiSimulator::~JingZiqiSimulator() {
  cv::destroyAllWindows();
  instance = nullptr;
}

void JingZiqiSimulator::start_game() {
  cv::namedWindow("井字棋游戏", cv::WINDOW_AUTOSIZE);
  // cv::setMouseCallback("井字棋游戏", mouse_callback_wrapper, nullptr);

  char first;
  // sr_->wait_receive(first);
  first = 'y'; // For testing, assume player wants to go first
  std::cout << "你想先手吗？(y/n): ";
  set_game_mode(true, first == 'y' || first == 'Y');

  std::cout << "\n井字棋游戏开始！\n";
  if (is_vs_computer) {
    std::cout << "你使用" << (is_player_first ? "黑子" : "白子") << "\n";
    std::cout << "AI使用" << (is_player_first ? "白子" : "黑子") << "\n";
  } else {
    std::cout << "黑子先手\n";
  }

  if (computer_piece == chessPiece::BLACK) {
    sr_->uart("#01@"); // AI先手
    std::cout << "AI先手，等待AI下棋...\n";
    ai_input[0] = chessPiece::BLACK; // AI先手下在第一个位置
    char ch;
    sr_->wait_receive(ch);
  }
  if (player_piece == chessPiece::BLACK) {
    char ch;
    std::cout << "玩家先手，等待玩家下棋...\n";
    sr_->wait_receive(ch); // 玩家先手
  }
  // chess_->detectGridByContours(img);
}

void JingZiqiSimulator::game_on_going(cv::Mat &img) {
  if (!before_wrong) {
    char ch;
    sr_->wait_receive(ch);
  }
  int pre_white = 0, pre_black = 0;
  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      if (board_state[i][j] == chessPiece::WHITE) {
        pre_white++;
      } else if (board_state[i][j] == chessPiece::BLACK) {
        pre_black++;
      }
    }
  }

  // 初始化检测数组
  std::array<chessPiece, 9> chessbox;
  for (int i = 0; i < 9; i++) {
    chessbox[i] = chessPiece::NONE;
  }

  // 获取图像识别结果
  chessbox = chess_->processImage(img);

  // 输出当前角色信息
  if (computer_piece == chessPiece::NONE) {
    std::cout << "AI棋子未设置，请先设置AI棋子" << std::endl;
    return;
  }

  // std::cout << "当前状态："
  //           << (computer_piece == chessPiece::BLACK ? "AI执黑" : "AI执白")
  //           << "，"
  //           << (player_piece == chessPiece::BLACK ? "玩家执黑" : "玩家执白")
  //           << std::endl;

  // std::cout << "当前回合："
  //           << (current_player == chessPiece::BLACK ? "黑方" : "白方")
  //           << std::endl;

  // 验证棋盘状态
  int none = 0, white = 0, black = 0;

  std::cout << "检测到的棋盘状态: [";
  for (int i = 0; i < 9; i++) {
    if (chessbox[i] == chessPiece::NONE) {
      std::cout << "0";
      none++;
    } else if (chessbox[i] == chessPiece::BLACK) {
      std::cout << "1";
      black++;
    } else if (chessbox[i] == chessPiece::WHITE) {
      std::cout << "2";
      white++;
    }
    if (i < 8)
    std::cout << ",";
  }
  std::cout << "]" << std::endl;

  if (none == 9) {
    // std::cout << "空盘警告" << std::endl;
    before_wrong = true;
    return;
  }
  // 验证棋盘状态是否合理
  if (none + black + white != 9 || black > 5 || white > 4 ||
      std::abs(black - white) > 1) {
    // std::cout << "检测到不合理的棋盘状态（空格:" << none << ", 黑子:" << black
    //           << ", 白子:" << white << "）" << std::endl;
    before_wrong = true;
    return;
  }

  if (!((black - pre_black == 1 && white == pre_white) ||
        (white - pre_white == 1 && black == pre_black))) {
    std::cout << "此帧数量与上一帧相比不合理，重新检测" << std::endl;
    before_wrong = true;
    return;
  }
  // 比较当前棋盘状态与记录的状态，检查变化
  std::vector<int> new_moves;     // 新增的棋子位置
  std::vector<int> removed_moves; // 消失的棋子位置

  for (int i = 0; i < 9; i++) {
    int row = i / GRID_SIZE;
    int col = i % GRID_SIZE;

    // 检测新增的棋子
    if (chessbox[i] != chessPiece::NONE &&
        board_state[row][col] == chessPiece::NONE) {
      new_moves.push_back(i);
    }
    // 检测消失的棋子
    if (chessbox[i] == chessPiece::NONE &&
        board_state[row][col] != chessPiece::NONE) {
      removed_moves.push_back(i);
    }
  }

  // 如果检测到棋子被移动（有新增和消失的棋子）
  // if (!new_moves.empty() && !removed_moves.empty()) {
  //   // 检查是否是AI的棋子被移动
  //   int from_pos = new_moves[0];
  //   int to_pos = removed_moves[0];
  //   int row = to_pos / GRID_SIZE;
  //   int col = to_pos % GRID_SIZE;

  //   if (board_state[row][col] == computer_piece) {
  //     std::cout << "检测到AI棋子被移动：从位置 " << from_pos + 1 << " 移回 "
  //               << to_pos + 1 << std::endl;
  //     // 发送移动命令并等待确认
  //     sr_->uart("#" + std::to_string(from_pos + 1) +
  //               std::to_string(to_pos + 1) + "@");
  //     char ch;
  //     sr_->wait_receive(ch);
  //     return;
  //   }
  // }
  // 检测新的移动并更新棋盘
  for (int i = 0; i < 9; i++) {
    int row = i / GRID_SIZE;
    int col = i % GRID_SIZE;

    // 发现新的棋子
    if (chessbox[i] != chessPiece::NONE &&
        board_state[row][col] == chessPiece::NONE) {
      // 确认是当前回合玩家的棋子
      if (chessbox[i] == current_player) {
        std::cout << (chessbox[i] == computer_piece ? "AI" : "玩家")
                  << "在位置 " << i + 1 << " (" << row << "," << col << ") 下棋"
                  << std::endl;

        // 更新棋盘状态
        board_state[row][col] = chessbox[i];
        draw_piece(row, col, chessbox[i]);

        // 检查游戏是否结束
        winner = check_winner();
        if (winner != chessPiece::NONE || is_draw()) {
          game_ended = true;
          show_game_result();
          cv::waitKey(3000); // 显示结果3秒
          reset_game();
          return;
        }

        // 切换回合
        switch_player();

        // 如果轮到AI且游戏未结束
        if (!game_ended && current_player == computer_piece) {
          std::cout << "轮到AI下棋..." << std::endl;
          auto [ai_row, ai_col] = get_best_move();
          if (ai_row != -1 && ai_col != -1) {
            int pos = ai_row * GRID_SIZE + ai_col;
            // 发送AI的移动命令
            sr_->uart("#0" + std::to_string(10-pos ) + "@");
            // 等待确认
            // sr_->uart("00");

            // 更新棋盘状态
            board_state[ai_row][ai_col] = computer_piece;
            draw_piece(ai_row, ai_col, computer_piece);

            // 检查游戏是否结束
            winner = check_winner();
            if (winner != chessPiece::NONE || is_draw()) {
              game_ended = true;
              show_game_result();
              cv::waitKey(3000);
              reset_game();
              return;
            }

            // 切换回合到玩家
            switch_player();
          }
        }
        break; // 完成这一轮的处理
      } else {
        std::cout << "检测到非当前回合玩家的移动！" << std::endl;
      }
    }
  }

  // 更新显示
  cv::imshow("井字棋游戏", canvas);
}

// void JingZiqiSimulator::mouse_callback_wrapper(int event, int x, int y,
//                                                int flags, void *userdata) {
//   if (instance && event == cv::EVENT_LBUTTONDOWN) {
//     instance->handle_mouse_click(x, y);
//   }
// }

void JingZiqiSimulator::handle_mouse_click(int col, int row) {
  if (game_ended)
    return;

  // 检查坐标是否有效
  if (row >= 0 && row < GRID_SIZE && col >= 0 && col < GRID_SIZE) {
    // 在人机对战模式下，只允许玩家在自己的回合下棋
    if (is_vs_computer && current_player != player_piece) {
      std::cout << "还没到你的回合！" << std::endl;
      return;
    }

    if (make_move(row, col)) {
      std::cout << "玩家 "
                << (current_player == chessPiece::BLACK ? "白子" : "黑子")
                << " 在 (" << row << ", " << col << ") 下棋\n";

      // 注意：在摄像头检测模式下，AI的移动由game_on_going函数处理
      // 这里只处理纯鼠标点击模式下的AI移动
      // 如果需要支持鼠标点击，可以添加一个标志位来区分模式
    }
  }
}

bool JingZiqiSimulator::make_move(int row, int col, chessPiece piece) {
  if (game_ended || !is_valid_position(row, col) ||
      board_state[row][col] != chessPiece::NONE) {
    return false;
  }

  // 如果没有指定棋子类型，使用当前玩家的棋子
  chessPiece piece_to_place =
      (piece == chessPiece::NONE) ? current_player : piece;

  // 下棋
  board_state[row][col] = piece_to_place;
  draw_piece(row, col, piece_to_place);

  winner = check_winner();
  // 检查游戏结果
  if (winner != chessPiece::NONE) {
    game_ended = true;
    std::cout << "game over";
  } else if (is_draw()) {
    std::cout << "game over";
    game_ended = true;
  }

  // 切换玩家
  if (!game_ended) {
    switch_player();
  }

  return true;
}

void JingZiqiSimulator::draw_board() {
  // 清空画布
  canvas = cv::Scalar(240, 240, 240);

  draw_grid();

  // 绘制现有棋子
  for (int row = 0; row < GRID_SIZE; row++) {
    for (int col = 0; col < GRID_SIZE; col++) {
      if (board_state[row][col] != chessPiece::NONE) {
        draw_piece(row, col, board_state[row][col]);
      }
    }
  }
}

void JingZiqiSimulator::draw_grid() {
  // 绘制垂直线
  for (int i = 1; i < GRID_SIZE; i++) {
    cv::line(canvas, cv::Point(i * CELL_SIZE, 0),
             cv::Point(i * CELL_SIZE, WINDOW_SIZE), cv::Scalar(0, 0, 0), 2);
  }

  // 绘制水平线
  for (int i = 1; i < GRID_SIZE; i++) {
    cv::line(canvas, cv::Point(0, i * CELL_SIZE),
             cv::Point(WINDOW_SIZE, i * CELL_SIZE), cv::Scalar(0, 0, 0), 2);
  }
}

void JingZiqiSimulator::draw_piece(int row, int col, chessPiece piece) {
  int center_x = col * CELL_SIZE + CELL_SIZE / 2;
  int center_y = row * CELL_SIZE + CELL_SIZE / 2;
  int radius = CELL_SIZE / 3;

  if (piece == chessPiece::BLACK) {
    // 绘制黑子
    cv::circle(canvas, cv::Point(center_x, center_y), radius,
               cv::Scalar(0, 0, 0), -1);
    cv::circle(canvas, cv::Point(center_x, center_y), radius,
               cv::Scalar(100, 100, 100), 2);
  } else if (piece == chessPiece::WHITE) {
    // 绘制白子
    cv::circle(canvas, cv::Point(center_x, center_y), radius,
               cv::Scalar(255, 255, 255), -1);
    cv::circle(canvas, cv::Point(center_x, center_y), radius,
               cv::Scalar(0, 0, 0), 2);
  }
}

chessPiece JingZiqiSimulator::check_winner() const {
  // 检查行
  for (int row = 0; row < GRID_SIZE; row++) {
    if (board_state[row][0] != chessPiece::NONE &&
        board_state[row][0] == board_state[row][1] &&
        board_state[row][1] == board_state[row][2]) {
      return board_state[row][0];
    }
  }

  // 检查列
  for (int col = 0; col < GRID_SIZE; col++) {
    if (board_state[0][col] != chessPiece::NONE &&
        board_state[0][col] == board_state[1][col] &&
        board_state[1][col] == board_state[2][col]) {
      return board_state[0][col];
    }
  }

  // 检查对角线
  if (board_state[0][0] != chessPiece::NONE &&
      board_state[0][0] == board_state[1][1] &&
      board_state[1][1] == board_state[2][2]) {
    return board_state[0][0];
  }

  if (board_state[0][2] != chessPiece::NONE &&
      board_state[0][2] == board_state[1][1] &&
      board_state[1][1] == board_state[2][0]) {
    return board_state[0][2];
  }

  return chessPiece::NONE;
}

bool JingZiqiSimulator::is_draw() const {
  for (int row = 0; row < GRID_SIZE; row++) {
    for (int col = 0; col < GRID_SIZE; col++) {
      if (board_state[row][col] == chessPiece::NONE) {
        return false;
      }
    }
  }
  return check_winner() == chessPiece::NONE;
}

void JingZiqiSimulator::switch_player() {
  current_player = (current_player == chessPiece::BLACK) ? chessPiece::WHITE
                                                         : chessPiece::BLACK;
}

void JingZiqiSimulator::show_game_result() {
  cv::Mat result_canvas = canvas.clone();

  std::string result_text;
  cv::Scalar text_color;

  if (winner == chessPiece::BLACK) {
    result_text = "Black Wins!";
    text_color = cv::Scalar(0, 0, 0);
  } else if (winner == chessPiece::WHITE) {
    result_text = "White Wins!";
    text_color = cv::Scalar(255, 255, 255);
  } else {
    result_text = "Draw!";
    text_color = cv::Scalar(128, 128, 128);
  }

  // 添加半透明背景
  cv::rectangle(result_canvas, cv::Point(50, WINDOW_SIZE / 2 - 50),
                cv::Point(WINDOW_SIZE - 50, WINDOW_SIZE / 2 + 50),
                cv::Scalar(200, 200, 200), -1);

  // 绘制结果文本
  cv::putText(result_canvas, result_text,
              cv::Point(WINDOW_SIZE / 2 - 100, WINDOW_SIZE / 2),
              cv::FONT_HERSHEY_SIMPLEX, 1.5, text_color, 3);

  cv::imshow("井字棋游戏", result_canvas);
}

std::vector<std::vector<chessPiece>>
JingZiqiSimulator::get_board_state() const {
  return board_state;
}

void JingZiqiSimulator::reset_game() {
  board_state = std::vector<std::vector<chessPiece>>(
      GRID_SIZE, std::vector<chessPiece>(GRID_SIZE, chessPiece::NONE));
  current_player = chessPiece::BLACK;
  game_ended = false;
  winner = chessPiece::NONE;
  draw_board();

  std::cout << "游戏重置，黑子先手\n";
}

bool JingZiqiSimulator::is_valid_position(int row, int col) const {
  return row >= 0 && row < GRID_SIZE && col >= 0 && col < GRID_SIZE;
}

chessPiece JingZiqiSimulator::get_current_player() const {
  return current_player;
}

bool JingZiqiSimulator::is_game_ended() const { return game_ended; }

chessPiece JingZiqiSimulator::get_winner() const { return winner; }

// AI相关函数实现
bool JingZiqiSimulator::is_board_full() const {
  for (const auto &row : board_state) {
    for (const auto &cell : row) {
      if (cell == chessPiece::NONE) {
        return false;
      }
    }
  }
  return true;
}

bool JingZiqiSimulator::has_winner(chessPiece piece) const {
  // 检查行
  for (int i = 0; i < GRID_SIZE; i++) {
    if (board_state[i][0] == piece && board_state[i][1] == piece &&
        board_state[i][2] == piece) {
      return true;
    }
  }

  // 检查列
  for (int j = 0; j < GRID_SIZE; j++) {
    if (board_state[0][j] == piece && board_state[1][j] == piece &&
        board_state[2][j] == piece) {
      return true;
    }
  }

  // 检查对角线
  if (board_state[0][0] == piece && board_state[1][1] == piece &&
      board_state[2][2] == piece) {
    return true;
  }
  if (board_state[0][2] == piece && board_state[1][1] == piece &&
      board_state[2][0] == piece) {
    return true;
  }

  return false;
}

int JingZiqiSimulator::minimax(std::vector<std::vector<chessPiece>> &board,
                               bool is_maximizing) {
  // 检查终止条件
  if (has_winner(computer_piece))
    return 1;
  if (has_winner(player_piece))
    return -1;
  if (is_board_full())
    return 0;

  if (is_maximizing) {
    int best_score = -2;
    for (int i = 0; i < GRID_SIZE; ++i) {
      for (int j = 0; j < GRID_SIZE; ++j) {
        if (board[i][j] == chessPiece::NONE) {
          board[i][j] = computer_piece;
          int score = minimax(board, false);
          board[i][j] = chessPiece::NONE;
          best_score = std::max(score, best_score);
        }
      }
    }
    return best_score;
  } else {
    int best_score = 2;
    for (int i = 0; i < GRID_SIZE; ++i) {
      for (int j = 0; j < GRID_SIZE; ++j) {
        if (board[i][j] == chessPiece::NONE) {
          board[i][j] = player_piece;
          int score = minimax(board, true);
          board[i][j] = chessPiece::NONE;
          best_score = std::min(score, best_score);
        }
      }
    }
    return best_score;
  }
}

std::pair<int, int> JingZiqiSimulator::get_best_move() {
  int best_score = -2;
  std::pair<int, int> best_move(-1, -1);

  for (int i = 0; i < GRID_SIZE; ++i) {
    for (int j = 0; j < GRID_SIZE; ++j) {
      if (board_state[i][j] == chessPiece::NONE) {
        board_state[i][j] = computer_piece;
        int move_score = minimax(board_state, false);
        board_state[i][j] = chessPiece::NONE;

        if (move_score > best_score) {
          best_score = move_score;
          best_move = std::make_pair(i, j);
        }
      }
    }
  }

  return best_move;
}

void JingZiqiSimulator::computer_move() {
  if (!is_vs_computer || game_ended)
    return;

  auto [row, col] = get_best_move();
  if (row != -1 && col != -1) {
    make_move(row, col, computer_piece);
    std::cout << "AI在位置 (" << row << ", " << col << ") 下棋" << std::endl;
    int num = row * GRID_SIZE + col + 1; // 转换为1-9的编号
    std::string msg = "#0" + std::to_string(11-num) + "@";
    sr_->uart(msg.c_str());
    char ch;
    sr_->wait_receive(ch); // 等待人下确认
  }
}

void JingZiqiSimulator::set_game_mode(bool vs_computer, bool player_first) {
  is_vs_computer = vs_computer;
  is_player_first = player_first;

  if (vs_computer) {
    if (player_first) {
      player_piece = chessPiece::BLACK;
      computer_piece = chessPiece::WHITE;
    } else {
      player_piece = chessPiece::WHITE;
      computer_piece = chessPiece::BLACK;
      // 如果电脑先手，立即执行一步
      computer_move();
    }
  }
}
